package com.service.tools.utls;

import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**工具类
 * @Author TangZuQiang
 * @Email tangzuqiang2021@126.com
 * @createTime 2023/12/12 19:33
 **/
public class ToolUtil {

    /* *
     * @Description  获取指定位数的随机字符串
     * @Author       tzq
     * @CreateTime   2023/12/12 19:33
     * @param: length
     * @return java.lang.String
     */
    public static String generateRandomString(int length) {
        String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int index = random.nextInt(characters.length());
            sb.append(characters.charAt(index));
        }
        return sb.toString();
    }

    /* *
     * @Description  验证密码是否符合规范
     * @Author       tzq
     * @CreateTime   2023/12/12 21:16
     * @param: password
     * @return boolean
     */
    public static boolean validatePassword(String password) {
        // 密码模式：包含大写字母、小写字母、数字和特殊字符，长度为8-20个字符
        String regex = "^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(.{8,20})$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(password);
//        Matcher matcher =  pattern.matcher(password);
        return matcher.matches();
    }

    /* *
     * @Description  无极分类
     * @Author       tangzuqiang
     * @Email        18982975988@189.cn
     * @CreateTime   2023/12/13 下午 5:44
     * @Param data:  要分类的数据
     * @Param pid:   父级id
     * @Param pidName: 父级字段名称
     * @Param children: 子级字段名称
     * @return     java.util.List<?>
     */
    public static List<Map<String, Object>>  promiseClassification(List<Map<String, Object>> data, int pid, String pidName, String children){
        List<Map<String, Object>> result = new ArrayList<>();
        int length = data.size();
        for(int i=0;i<length;i++){
            Map<String,Object> item = (Map<String, Object>) data.get(i);
            Integer cPid = Integer.parseInt(item.get(pidName).toString());
            Integer id   = Integer.parseInt(item.get("id").toString());
            if ( cPid == pid){
                //组装新的结构型数据
                List<Map<String,Object>> ch = (List<Map<String, Object>>) ToolUtil.promiseClassification(data,id,pidName,children);
                item.put(children,ch);
                result.add(item);

            }
        }
        return result;
    }



    /* *
     * @Description  将时间字符转为指定格式时间字符串
     * @Author       tzq
     * @CreateTime   2023/12/19 15:46
     * @param: time 参数1:时间字符串 参数: 时间格式
     * @return java.util.Date
     */
    public static String getSpecifyFormatByStrtime(String... time)  {
        String inputTime = "";
        String format = "yyyy-MM-dd HH:mm:ss";
        TimeZone timeZone = TimeZone.getTimeZone("GMT-8");
        String outFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
        switch (time.length) {
            case 4:
                outFormat = time[3];
            case 3:
                timeZone = TimeZone.getTimeZone(time[2]);
            case 2:
                format = time[1];
            case 1:
                inputTime = time[0];


        }

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        simpleDateFormat.setTimeZone(timeZone);
        Date date = null;
        try {
            date = simpleDateFormat.parse(inputTime);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //时间刚好多了1天
        calendar.add(Calendar.DAY_OF_MONTH,-1);
        date = calendar.getTime();
        simpleDateFormat = new SimpleDateFormat(outFormat);


        return simpleDateFormat.format(date);
    }

    /* *
     * @Description  增减时间天数
     * @Author       tzq
     * @CreateTime   2024/1/22 20:57
     * @param: day
     * @return java.lang.String
     */
    public static String increaseDecreaseDay(int day){
        SimpleDateFormat simpleDateFormat = new
                SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DAY_OF_MONTH,day);
        simpleDateFormat.setCalendar(instance);
        return  simpleDateFormat.format(instance.getTime());
    }

    /* *
     * @Description  增加小时时间
     * @Author       tzq
     * @CreateTime   2024/1/26 9:58
     * @param: hour
     * @return java.lang.String
     */
    public static String increaseDecreaseHour(int hour){
        SimpleDateFormat simpleDateFormat = new
                SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.HOUR,hour);
        simpleDateFormat.setCalendar(instance);
        return  simpleDateFormat.format(instance.getTime());
    }


    /* *
     * @Description  将时间字符串转为时间戳
     * @Author       tzq
     * @CreateTime   2024/1/4 12:01
     * @param: args
     * @return long
     */
    public static long timeToTimestampConversion(String... args){
        String dateStr = "";
        String format = "yyyy-MM-dd HH:mm:ss";
        switch (args.length) {
            case 2:
                format = args[1];
            case 1:
                dateStr = args[0];

        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        try {
            Date parse = simpleDateFormat.parse(dateStr);
            return parse.getTime() / 1000;
        } catch (ParseException e) {
            return 0;
        }


    }

    /* *
     * @Description  utc时间转上海时间
     * @Author       tzq
     * @CreateTime   2024/1/5 16:12
     * @param: inputTime
     * @return java.lang.String
     */
    public static String utcToShangHai(String inputTime) {


        String format = "yyyy-MM-dd'T'HH:mm:ss";
//        String inputTime = "2024-01-04 12:01:01";
        String outFormat = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

        Date date = null;
        try {
            date = simpleDateFormat.parse(inputTime);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        return simpleDateFormat.format(date);
    }

    /* *
     * @Description  获取当前时间
     * @Author       tzq
     * @CreateTime   2024/1/12 10:36
     * @return java.lang.String
     */
    public static String getTime() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(new Date());

    }

    /* *
     * @Description  获取上海时区当前时间
     * @Author       tzq
     * @CreateTime   2024/3/6 11:06
     * @return java.lang.String
     */
    public static String getShangHaiTime() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        return simpleDateFormat.format(new Date());
    }

    /* *
     * @Description  获取增加时间的上海时区字符串
     * @Author       tzq
     * @CreateTime   2024/3/6 11:12
     * @param: days
     * @return java.lang.String
     */
    public static String getSpecifyDaysShangHaiTime(int days,String format) {
        if(format==null||format.equals("")){
            format="yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
//        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        Calendar calendar = Calendar.getInstance();
//        calendar.setTime(new Date());
        calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        calendar.add(Calendar.DATE, days);
        return simpleDateFormat.format(calendar.getTime());
    }

    /* *
     * @Description  获取jar包允许目录
     * @Author       tzq
     * @CreateTime   2024/1/22 14:02
     * @return java.lang.String
     */
    public static String getRunDir(){
        return System.getProperty("user.dir");

    }

    /* *
     * @Description  执行shell命令并抛出异常
     * @Author       tzq
     * @CreateTime   2022/10/20 20:57
     * @param: cmd
     * @return java.lang.String
     */
    public static String execException(String cmd) throws Exception {

        String[] cmdA = {"/bin/sh", "-c", cmd};
        Process process = Runtime.getRuntime().exec(cmdA);
        String s = contentInStream(process.getInputStream());
        if (Boolean.TRUE.equals(isEmpty(s))) {
            if (Boolean.TRUE.equals(isNotEmpty(process.getErrorStream()))) {
                String errors = contentInStream(process.getErrorStream());
                //如有错误返回错误
                if (StringUtils.isNotEmpty(errors)) throw new RuntimeException(errors + "\n" + cmd);

            }

        }
        process.destroy();//释放资源
        return s;
    }

    /**
     * 将InputStream转为字符串
     *
     * @param stream
     * @return
     * @throws IOException
     */
    public static String contentInStream(InputStream stream) throws IOException {
        return contentInReader(new InputStreamReader(stream));
    }


    /**
     * 解析Reader 为字符串
     *
     * @param reader
     * @return
     * @throws IOException
     */
    public static String contentInReader(Reader reader) throws IOException {
        BufferedReader br = new BufferedReader(reader);
        String line;
        StringBuilder content = new StringBuilder();
        while ((line = br.readLine()) != null) {
            content.append(line).append("\n");
        }
        return content.toString();
    }

    /* *
     * @Description  判断输入值是否为空
     * @Author       Tangzuqiang
     * @Email        tangzuqiang2021@126.com
     * @CreateTime   2021/07/27 上午 10:22
     * @Param input:
     * @return     java.lang.Boolean
     */
    public static Boolean isEmpty(Object input){
        if (input == null)
            return true;
        boolean result = false;
        if (input instanceof ArrayList) {
            result = ((ArrayList<?>) input).isEmpty();
        } else if (input instanceof Map) {
            result = ((Map<?, ?>) input).isEmpty();
        } else if (input instanceof String[]) {
            result = ((String[]) input).length == 0;
        } else if (input instanceof Integer[]) {
            result = ((Integer[]) input).length == 0;
        } else if (input instanceof String) {
            result = "".equals(input) || ((String) input).isEmpty();
        } else if (input instanceof Integer) {
            result = input.equals(0);
        } else if (input instanceof Boolean) {
            result = input.equals(false);
        } else if (input instanceof BigDecimal) {
            result = ((BigDecimal) input).compareTo(BigDecimal.valueOf(0.00)) > 1;
        }else if(input instanceof List){
            result = ((List<?>)input).isEmpty();
        }
        return result;
    }


    /* *
     * @Description  判断对象是否不为空
     * @Author       tzq
     * @CreateTime   2022/7/11 18:14
     * @param: input
     * @return java.lang.Boolean
     */
    public static Boolean isNotEmpty(Object input){
        return !isEmpty(input);
    }

    /* *
     * @Description  判断字符串中是否包含字母和数字
     * @Author       tzq
     * @CreateTime   2024/1/22 20:09
     * @param: str
     * @return boolean true 包含
     */
    public static boolean containsNumberAndLetter(String str) {
        // 定义匹配规则
        String regex = "\\w+|.*\\w+|.*\\w+.*";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }


    /* *
     * @Description  根据指定时间字符串和格式获取上个月的时间
     * @Author       tzq
     * @CreateTime   2024/2/28 20:39
     * @param: inputDateStr
     * @param: format
     * @return java.lang.String
     */
    public static String getLastMonth(String inputDateStr,String format){
//        String inputDateStr = "2022-06-15";
        if (format == null) {
            format = "yyyy-MM-dd";
        }

        LocalDate inputDate = LocalDate.parse(inputDateStr, DateTimeFormatter.ofPattern(format));
        LocalDate lastMonthDate = inputDate.minusMonths(1);
        String lastMonthDateStr = lastMonthDate.format(DateTimeFormatter.ofPattern(format));
//        System.out.println("上个月的时间是: " + lastMonthDateStr);
        return lastMonthDateStr;
    }

    /* *
     * @Description  获取异常信息
     * @Author       tzq
     * @CreateTime   2024/2/29 11:27
     * @param: ex
     * @return java.lang.String
     */
    public static String getExceptionMessage(Exception ex) {
        StringWriter stringWriter= new StringWriter();
        PrintWriter writer= new PrintWriter(stringWriter);
        ex.printStackTrace(writer);
        StringBuffer buffer= stringWriter.getBuffer();
        return buffer.toString();
    }

    /* *
     * @Description  实体转map
     * @Author       tzq
     * @CreateTime   2024/3/6 18:11
     * @param: entity
     * @return java.util.Map<java.lang.String,java.lang.Object>
     */
    public static <T> Map<String, Object> entityToMap(T entity) throws IllegalAccessException {
        Class<?> clazz = entity.getClass();
        Map<String, Object> resultMap = new HashMap<>();

        for (Field field : clazz.getDeclaredFields()) {
            // 设置字段为可访问
            field.setAccessible(true);

            // 获取字段的名称和值
            String fieldName = field.getName();
            Object fieldValue = field.get(entity);

            // 将属性名和属性值放入Map中
            resultMap.put(fieldName, fieldValue);
        }

        return resultMap;
    }

    /* *
     * @Description  map排序
     * @Author       tzq
     * @CreateTime   2024/5/15 14:02
     * @param: map
     * @param: key
     * @param: orderBy
     * @return java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.Long>>
     */
    public static Map<String,Map<String,Long>> mapOrderBy(Map<String, Map<String,Long>> map,String key, String orderBy) {
        List<Map.Entry<String, Map<String, Long>>> list = new ArrayList<>(map.entrySet());
        if ("asc".equals(orderBy)) {
            Collections.sort(list, (o1, o2) -> o1.getValue().get(key).compareTo(o2.getValue().get(key)));
        } else if ("desc".equals(orderBy)) {
            Collections.sort(list, (o1, o2) -> o2.getValue().get(key).compareTo(o1.getValue().get(key)));
        }

        Map<String, Map<String, Long>> resultMap = new LinkedHashMap<>();
        for (Map.Entry<String, Map<String, Long>> entry : list) {
            resultMap.put(entry.getKey(), entry.getValue());
        }
        return resultMap;
    }
}
